/*
 * SystemLogger.java
 *
 * Created on February 12, 2007, 7:54 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package ca.uvic.group2.server;
import ca.uvic.group2.testHarness.Command;
import java.io.*;
import java.util.*;

/**
 *
 * @author pat
 */
public class SystemLogger {
    public static final int USER_COMM = 0;
    public static final int ACCT_TRAN = 1;
    public static final int SYSM_EVNT = 2;
    public static final int QUOT_SERV = 3;
    public static final int ERRO_EVNT = 4;
    public static final int DEBG_EVNT = 4;

    public static final int ACT_ADD = 0;
    public static final int ACT_RMV = 1;

    private final String[] tags= {  "userCommand",
                                    "accountTransaction",
                                    "systemEvent",
                                    "quoteServer",
                                    "errorEvent",
                                    "debugEvent"};
    private final String[] accountActions = {   "add",
                                                "remove"};

    private String filename;
    private BufferedWriter w;


    /** Creates a new instance of SystemLogger */
    public SystemLogger(String filename) {
        this.filename = filename;
        try {
            w = new BufferedWriter(new FileWriter(filename));
            w.write("<?xml version=\"1.0\"?>\n");
            w.write("<log>\n");
            w.flush();
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
        }
    }//endMethod

    public void closeLog() {
        try {
            System.out.println("Closing log file.");
            w.write("</log>\n");
            w.close();
        } catch(IOException e) {
            System.err.println("Can't Close Log file");
            e.printStackTrace();
        }
    }//endMethod

    private String openCommTag(int commType) {
        StringBuffer s = new StringBuffer();
        s.append("\t<"+ tags[commType] +">\n");
        return s.toString();
    }//endMethod

    private String timestamp(long timestamp) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<timestamp>");
        s.append(timestamp);
        s.append("</timestamp>\n");
        return s.toString();
    }//endMethod

    private String serverTag(String sname) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<server>");
        s.append(sname);
        s.append("</server>\n");
        return s.toString();
    }//endMethod

    private String transNumTag(int num) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<transactionNum>");
        s.append(num);
        s.append("</transactionNum>\n");
        return s.toString();
    }//endMethod

    private String commandTag(String comm) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<command>");
        s.append(comm);
        s.append("</command>\n");
        return s.toString();
    }//endMethod

    private String actionTag(String action) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<action>");
        s.append(action);
        s.append("</action>\n");
        return s.toString();
    }//endMethod

    private String userTag(String uname) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<username>");
        s.append(uname);
        s.append("</username>\n");
        return s.toString();
    }//endMethod

    private String stockTag(String sSymbol) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<stockSymbol>");
        s.append(sSymbol);
        s.append("</stockSymbol>\n");
        return s.toString();
    }//endMethod

    private String fileTag(String fname) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<filename>");
        s.append(fname);
        s.append("</filename>\n");
        return s.toString();
    }//endMethod

    private String fundsTag(double amount) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<funds>");
        s.append(amount);
        s.append("</funds>\n");
        return s.toString();
    }//endMethod

    private String priceTag(double amount) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<price>");
        s.append(amount);
        s.append("</price>\n");
        return s.toString();
    }//endMethod

    private String quoteTimeTag(long time) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<quoteServerTime>");
        s.append(time);
        s.append("</quoteServerTime>\n");
        return s.toString();
    }//endMethod

    private String crypKeyTag(String key) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<cryptokey>");
        s.append(key);
        s.append("</cryptokey>\n");
        return s.toString();
    }//endMethod

    private String errorTag(String e) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<errorMessage>");
        s.append(e);
        s.append("</errorMessage>\n");
        return s.toString();
    }//endMethod

    private String debugTag(String d) {
        StringBuffer s = new StringBuffer();
        s.append("\t\t<debugMessage>");
        s.append(d);
        s.append("</debugMessage>\n");
        return s.toString();
    }//endMethod

    private String closeCommTag(int commType) {
        StringBuffer s = new StringBuffer();
        s.append("\t</"+ tags[commType] +">\n");
        return s.toString();
    }//endMethod

    /*
     * Method: logUserCommand
     * Description: Call this when the system receives a command from either
     * command file or web form.
     * Precondition: Most have a instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  command - name of the command being called
     *  username - name of user calling command (optional)
     *  stockSymbol - What stock is going to be effected. (optional)
     *  filename - name of fle that maybe referenced (optional)
     *  amount - number of funds in question (optional)
     *  NOTE: pass null or negative value if the entry is not required and optional
     *
     */
    public boolean logUserCommand(long timestamp,
                                  String server,
                                  int transNum,
                                  String command,
                                  String username,
                                  String stockSymbol,
                                  String filename,
                                  double amount) {
        try {
            w.write(openCommTag(USER_COMM));
            w.write(timestamp(timestamp));
            w.write(serverTag(server));
            w.write(transNumTag(transNum));
            w.write(commandTag(command));
            if(username != null)
                w.write(userTag(username));
            if(stockSymbol != null)
                w.write(stockTag(stockSymbol));
            if(filename != null)
                w.write(fileTag(filename));
            if(amount >= 0)
                w.write(fundsTag(amount));
            w.write(closeCommTag(USER_COMM));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod


    /*
     * Method: logQuoteServer
     * Description: Call this when the system gets results back from the
     *              Legacy Quote Server.
     * Precondition: Most have a instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  amount - number of funds in question
     *  stockSymbol - What stock is going to be effected.
     *  username - name of user calling command
     *  qstime - Time the quote server was hit (passed by quote server)
     *  cypkey - the encoded key from quote server.
     *
     */
    public boolean logQuoteServer(long timestamp,
                                  String server,
                                  int transNum,
                                  double amount,
                                  String stockSymbol,
                                  String username,
                                  long qstime,
                                  String cypkey) {
        try {
            w.write(openCommTag(QUOT_SERV));
            w.write(timestamp(timestamp));
            w.write(serverTag(server));
            w.write(transNumTag(transNum));
            w.write(priceTag(amount));
            w.write(stockTag(stockSymbol));
            w.write(userTag(username));
            w.write(quoteTimeTag(qstime));
            w.write(crypKeyTag(cypkey));
            w.write(closeCommTag(QUOT_SERV));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod


    /*
     * Method: logAccountTransaction
     * Description: Call this when the system adds or removes cash from an account.
     * Precondition: Most have instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  action - As defined by constants ACT_ADD, ACT_RMV
     *  username - name of user calling command
     *  funds - number of funds in question
     *
     */
    public boolean logAccountTransaction(long timestamp,
                                         String server,
                                         int transNum,
                                         int action,
                                         String username,
                                         double funds) {
        try {
            if (action != ACT_ADD && action != ACT_RMV)
                return false;
            w.write(openCommTag(ACCT_TRAN));
            w.write(timestamp(timestamp));
            w.write(serverTag(server));
            w.write(transNumTag(transNum));
            w.write(actionTag(accountActions[action]));
            w.write(userTag(username));
            w.write(fundsTag(funds));
            w.write(closeCommTag(ACCT_TRAN));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod

    private String makeSystemMessage(long timestamp,
                                     String server,
                                     int transNum,
                                     String command,
                                     String username,
                                     String stockSymbol,
                                     String filename,
                                     double funds) {
        StringBuffer s = new StringBuffer();
        s.append(timestamp(timestamp));
        s.append(serverTag(server));
        s.append(transNumTag(transNum));
        s.append(commandTag(command));
        if(username != null)
            s.append(userTag(username));
        if(stockSymbol != null)
            s.append(stockTag(stockSymbol));
        if(filename != null)
            s.append(fileTag(filename));
        if(funds >= 0)
            s.append(fundsTag(funds));
        return s.toString();
    }

    /*
     * Method: logSystemEvent
     * Description: Call this when the system receives a command from either
     * command file or web form.
     * Precondition: Most have a instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  command - name of the command being called
     *  username - name of user calling command (optional)
     *  stockSymbol - What stock is going to be effected. (optional)
     *  filename - name of fle that maybe referenced (optional)
     *  funds - number of funds in question (optional)
     *  NOTE: pass null or a negative value if the entry is not applicable
     *
     */
    public boolean logSystemEvent(long timestamp,
                                  String server,
                                  int transNum,
                                  String command,
                                  String username,
                                  String stockSymbol,
                                  String filename,
                                  double funds) {
        try {
            w.write(openCommTag(SYSM_EVNT));
            w.write(makeSystemMessage(timestamp, server, transNum, command,
                                      username, stockSymbol, filename, funds));
            w.write(closeCommTag(SYSM_EVNT));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod

    /*
     * Method: logErrorEvent
     * Description: Call this when the system receives a command from either
     * command file or web form.
     * Precondition: Most have a instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  command - name of the command being called
     *  username - name of user calling command (optional)
     *  stockSymbol - What stock is going to be effected. (optional)
     *  filename - name of fle that maybe referenced (optional)
     *  funds - number of funds in question (optional)
     *  errorMessage - a description of the error (optional)
     *  NOTE: pass null or a negative value if the entry is not applicable
     *
     */
    public boolean logErrorEvent(long timestamp,
                                 String server,
                                 int transNum,
                                 String command,
                                 String username,
                                 String stockSymbol,
                                 String filename,
                                 double funds,
                                 String errorMessage) {
        try {
            w.write(openCommTag(ERRO_EVNT));
            w.write(makeSystemMessage(timestamp, server, transNum, command, username, stockSymbol, filename, funds));
            if(errorMessage != null)
                w.write(errorTag(errorMessage));
            w.write(closeCommTag(ERRO_EVNT));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod

    /*
     * Method: logDebugEvent
     * Description: Call this when the system receives a command from either
     * command file or web form.
     * Precondition: Most have a instancated this class properly
     * Parameters:
     *  server - Systems name for a server.
     *  transNum - A unique transaction number for a transation within the
     *             system.
     *  command - name of the command being called
     *  username - name of user calling command (optional)
     *  stockSymbol - What stock is going to be effected. (optional)
     *  filename - name of fle that maybe referenced (optional)
     *  funds - number of funds in question (optional)
     *  debugMessage - a message to help with debuging (optional)
     *  NOTE: pass null or a negative value if the entry is not applicable
     *
     */
    public boolean logDebugEvent(long timestamp,
                                 String server,
                                 int transNum,
                                 String command,
                                 String username,
                                 String stockSymbol,
                                 String filename,
                                 double funds,
                                 String debugMessage) {
        try {
            w.write(openCommTag(DEBG_EVNT));
            w.write(makeSystemMessage(timestamp, server, transNum, command, username, stockSymbol, filename, funds));
            if(debugMessage != null)
                w.write(errorTag(debugMessage));
            w.write(closeCommTag(DEBG_EVNT));
            w.flush();
            return true;
        } catch(IOException e) {
            System.err.println("Can't Open Log file");
            e.printStackTrace();
            return false;
        }//endTryCatch
    }//endMethod

}
